/**
  ******************************************************************************
  * @file    shell-history.c
  * @author  Iron
  * @date    2021-02-02
  * @version v1.0
  * @brief   shell-history c file
  */

/** @addtogroup GROUP_SHELL
  * @{
  */

/* Private includes ----------------------------------------------------------*/
#include "shell_history.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

int shell_history_init(struct shell_history_queue_t *history)
{
    struct shell_history_head_t *phead;

    shell_assert(history);

    phead = &history->head;

    TAILQ_INIT(phead);

    history->current = TAILQ_FIRST(phead);

    return 0;
}

void shell_history_reset(shell_context_t *sh)
{
    struct shell_history_head_t *phead;

    if (sh->shell_history != NULL)
    {
        phead = &sh->shell_history->head;
        sh->shell_history->current = TAILQ_FIRST(phead);   // 更新第一个记录
    }
}

int shell_history_append(shell_context_t *sh, const char *cmd, int len)
{
    struct shell_history_head_t *phead;
    struct shell_history_t *elm, *next;
    int total;

    if (len <= 0 || sh->shell_history == NULL)
        return 0;

    /* insert new elment */
    elm = sh->shell_malloc(sizeof(struct shell_history_t));

    if (elm == NULL)
        return 0;

    memset(elm, 0, sizeof(struct shell_history_t));

    elm->commands = sh->shell_malloc(len + 1);

    if (elm->commands == NULL)
    {
        sh->shell_free(elm);
        return 0;
    }

    strncpy(elm->commands, cmd, len);
    elm->commands[len] = '\0';
    phead = &sh->shell_history->head;

    TAILQ_INSERT_HEAD(phead, elm, entries); // 插入数据
    sh->shell_history->current = TAILQ_FIRST(phead);   // 更新第一个记录

    /* clear histroy */
    total = 0;

    for (elm = phead->tqh_first; elm != NULL; elm = next)
    {
        next = elm->entries.tqe_next;

        total += 1;

        if (total > SHELL_HISTORY_NUM)
        {
            TAILQ_REMOVE(phead, elm, entries);

            sh->shell_free(elm->commands);
            sh->shell_free(elm);
        }
    }

    return total;
}

int shell_history_last(shell_context_t *sh, char *buf, int bufsize)
{
    struct shell_history_t *elm;

    shell_assert(sh->shell_history);

    elm = sh->shell_history->current;

    if (elm == NULL)
        return 0;

    strncpy(buf, elm->commands, bufsize);

    elm = TAILQ_NEXT(elm, entries);

    if (elm != NULL)
        sh->shell_history->current = elm;

    return strlen(buf);
}

int shell_history_next(shell_context_t *sh, char *buf, int bufsize)
{
    struct shell_history_head_t *phead;
    struct shell_history_t *elm;

    shell_assert(sh->shell_history);

    phead = &sh->shell_history->head;
    elm = sh->shell_history->current;

    if (elm == NULL)
        return 0;

    if (elm != TAILQ_FIRST(phead))
    {
        elm = TAILQ_PREV(elm, shell_history_head_t, entries);

        strncpy(buf, elm->commands, bufsize);

        sh->shell_history->current = elm;
    }

    return strlen(buf);
}




/**
  * @}
  */

/******************* (C)COPYRIGHT 2021 ***** END OF FILE *********************/
